<template>
  <div class="product-table">
    <div class="toolMenu">
      <div class="flex">
        <el-input v-model="searchKey" :size="size" clearable placeholder="按资产编号查询"/>
        <el-button type="primary" :size="size" style="margin-left: 5px" :icon="Search" @click="searchData">查询</el-button>
        <el-button type="primary" :size="size" style="margin-left: 5px" @click="searchWeek('pre')">上一周</el-button>
        <el-button type="primary" :size="size" style="margin-left: 5px" @click="searchWeek('next')">下一周</el-button>
      </div>
      <div>
        <el-button type="primary" :size="size" :icon="Setting" @click="setMenu" circle />
        <el-button type="primary" :size="size" v-show="!isFullscreen" :icon="FullScreen" title="全屏" @click="toggle" circle />
        <el-button type="primary" :size="size" v-show="isFullscreen" :icon="CloseBold" title="关闭全屏" @click="toggle" circle />
      </div>
    </div>
    <el-table
        :data="tableObj.data"
        border
        stripe
        :header-cell-class-name="() => 'headerClass'"
        :cell-style="cellStyle"
        :span-method="objectSpanMethod"
        empty-text="暂无数据"
        style="width: 100%; height: 91%">
      <el-table-column type="index" fixed="left" label="#" align="center"/>
      <template v-for="item in tableObj.columns">
        <el-table-column
            v-if="!item.children"
            :key="item.key"
            :prop="item.key"
            align="center"
            :label="item.title"
            :fixed="item.fixed"
            :width="item.width">
          <template #default="scope">
            <span>{{ tableData(scope.row, item) }}</span>
          </template>
        </el-table-column>
        <el-table-column
            v-else
            :key="item.key"
            align="center"
            :label="item.title">
          <el-table-column v-for="it in item.children"
                           :key="it.key"
                           :prop="it.key"
                           align="center"
                           :label="it.title"
                           :width="it.width">
            <template #default="scope">
              <div class="text-transparent" :style="handleColColor(scope.row, scope.row[it.key])">{{scope.row[it.key]}}</div>
            </template>
          </el-table-column>
        </el-table-column>
      </template>
    </el-table>
    <tool-menu-modal ref="toolMenu" @confirm="confirmModal"/>
  </div>
</template>

<script setup lang="ts">
import {
  defaultColumn,
  defaultColumnType,
  getDefaultRangeTime,
  mergeColumn,
  randomColor,
  getWeekDates,
  dateFormat,
  size
} from "@/views/defaultData";
import {nextTick, onMounted, reactive, ref} from "vue";
import {Setting, FullScreen, CloseBold, Search} from '@element-plus/icons-vue'
import { ElLoading } from 'element-plus'
import axios from 'axios';
import { useFullscreen } from '@vueuse/core'
import ToolMenuModal from "@/views/ToolMenuModal.vue";

const toolMenu = ref(null);
let colorMap = {};
let timeRange = getDefaultRangeTime();
let searchKey = ref('');
let columnType = ref(defaultColumnType);
let searchTimeRange = getWeekDates();
const tableObj = reactive({
  data: [],
  columns: [],
  loading: null,
  startHour: 0,
  endHour: 23,
  dyColumn: [],
});
const selectRadomColor = randomColor();
const { toggle, isFullscreen } = useFullscreen();

function setMenu() {
  toolMenu.value.open({
    unit: columnType.value,
    timeRange: [tableObj.startHour, tableObj.endHour]
  });
}

function searchWeek(flag) {
  let date = new Date(searchTimeRange.endDate).getTime() + 24 * 60 * 60 * 1000;
  if (flag === 'pre') {
    date = new Date(searchTimeRange.startDate).getTime() - 24 * 60 * 60 * 1000;
  }
  searchTimeRange = getWeekDates(date);
  console.log(searchTimeRange);
  init({timeRange});
}
function initHour(timeRange) {
  const [startTime, endTime] = timeRange;
  tableObj.startHour = new Date(startTime).getHours();
  tableObj.endHour = new Date(endTime).getHours();
}

function initData() {
  axios.get('/data.json').then(res => {
    let data = res.data;
    if (searchKey.value) {
      data = data.filter(item => item[mergeColumn] === searchKey.value);
    }
    if (data.length) {
      handleColumn(data, ({dyColumns, dyColumn}) => {
        tableObj.columns = defaultColumn.concat(dyColumns);
        tableObj.dyColumn = dyColumn;
        handleData(data);
      });
    }
  }).catch(err => {
    console.log(err);
  })
}

function init({timeRange}) {
  tableObj.loading = ElLoading.service({
    lock: true,
    text: '数据加载中，请稍等...',
    background: 'rgba(122, 122, 122, 0.8)',
  })
  initHour(timeRange);
  initData();
}

function searchData() {
  init({
    timeRange
  })
}

function objectSpanMethod({row, rowIndex, columnIndex}) {
  if (columnIndex === 1) {
    const currentValue = row[mergeColumn];
    const preRow = tableObj.data[rowIndex - 1];
    const preValue = preRow ? preRow[mergeColumn] : null;
    if (currentValue === preValue) {
      return {rowspan: 0, colspan: 0};
    } else {
      let rowspan = 1;
      for (let i = rowIndex + 1; i < tableObj.data.length; i++) {
        const nextRow = tableObj.data[i];
        const nextValue = nextRow[mergeColumn];
        if (nextValue === currentValue) {
          rowspan++;
        } else {
          break;
        }
      }
      return {rowspan, colspan: 1};
    }
  }
}

function confirmModal({workTime, unit}) {
  timeRange = workTime;
  columnType.value = unit;
  init({
    timeRange: workTime
  });
}

function handleColumn(data, callback) {
  const {startHour, endHour} = tableObj;
  let worker = new Worker('/columnWorker.js');
  worker.postMessage({
    data,
    startHour,
    endHour,
    type: columnType.value
  });
  worker.onmessage = function(event){
    callback(event.data);
  };
}
function handleData(data) {
  data.forEach(item => {
    const {startTime, endTime} = item;
    if (startTime.includes(':') && endTime.includes(':')) {
      let sTime = new Date(startTime).getTime();
      const eTime = new Date(endTime).getTime();
      let accrual = 60 * 60 * 1000;
      if (columnType.value === defaultColumnType) {
        accrual *= 24;
      }
      for (let i = sTime; i < eTime; i += accrual) {
        let date = dateFormat(i, columnType.value);
        let key = `${date}-${columnType.value === defaultColumnType ? new Date(i).getDate()
            : new Date(i).getHours()}`;
        if (tableObj.dyColumn.includes(key)) {
          item[key] = 1;
        }
      }
    }
    if (!colorMap[item.id]) {
      colorMap[item.id] = selectRadomColor();
    }
  });
  tableObj.data = data
  nextTick(() => {
    tableObj.loading.close();
  })
}

function handleColColor(row, data) {
  let obj = {
    'background': 'none'
  }
  if (data === 1) {
    obj['background'] = colorMap[row.id];
  }
  return obj;
}

function cellStyle({column}) {
  if (/(\d+\/)+\d+\-\d+/.test(column.property)) {
    return {
      'border-right': 'none !important',
      'border-bottom': 'none !important'
    }
  }
}

function tableData(row, item) {
  if (item.type === 'date') {
    return dateFormat(row[item.key])
  }
  return row[item.key]
}

onMounted(() => {
  init({
    timeRange
  });
})
</script>

<style>
.headerClass {
  background-color: #e3f6f6 !important;
}
</style>

<style scoped>
.flex {
  display: flex;
}
.text-transparent {
  color: transparent;
}
.toolMenu {
  display: flex;
  justify-content: space-between;
  margin-bottom: 5px;
}
.product-table {
  width: 99%;
  margin: 1% auto;
  height: calc(100vh);
  box-sizing: inherit;
}
:deep(.el-table .cell) {
  line-height: normal;
  padding: 0;
}
:deep(.el-table .el-table__cell) {
  padding: 4px 0;
}
</style>
